package com.ruoyi.livesass.api.sync;

import java.math.BigDecimal;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cyl.manager.ums.mapper.MemberMapper;
import com.google.common.collect.Maps;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.livesass.LiveVideoService;
import com.ruoyi.livesass.api.domain.LbsGksc;
import com.ruoyi.livesass.api.domain.LbsZbrqsj;
import com.ruoyi.livesass.api.mapper.LbsZbrqsjMapper;
import com.ruoyi.livesass.api.service.LbsZbrqsjService;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.service.ISysConfigService;
import com.volcengine.model.livesaas.response.GetActivityAPIResponse;
import com.volcengine.model.livesaas.response.GetPageWatchDataAPIV2Response.PageClicksFormAPI;
import com.volcengine.model.livesaas.response.GetRealTimeOnlineNumberAPIResponse;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.StrUtil;

/**
 * @ClassName: LiveActivityDataSynService
 * @Description: TODO(直播数据实时统计-当直播间开始后就进行数据拉取)
 * @author 晏大兵
 * @date 2025年2月10日 上午11:13:23
 */
@Component("liveActivityDataSyn")
@Order(3)
public class LiveActivityDataSynService implements ApplicationRunner {
	
	private static final Logger LOG = LoggerFactory.getLogger(LiveActivityDataSynService.class);
	
	@Autowired
	LiveVideoService liveVideoService;
	
	@Autowired
	LbsZbrqsjService lbsZbrqsjService;
	
    @Autowired
    LbsZbrqsjMapper lbsZbrqsjMapper;
	
	@Autowired
	MemberMapper memberMapper;
	
	@Autowired
	private ISysConfigService configService;
	
    @Autowired
    private RedisCache redisCache;
    
    @Autowired
    public RedisTemplate redisTemplate;
    
    private String cacheKey = "activityDataSyn_";
	
	@Value("${custom.synTaskEnable}")
	private boolean synTaskEnable;
	
	private Map<String, Long> subNameDeptid = Maps.newHashMap();
	
	
	public static void main(String...args) {
		String key = "activityDataSyn_dfhuf520@126.com_1827550502393204";
		System.out.println(key.split("_")[2]);
	}
	
	
	@Override
	public void run(ApplicationArguments args) throws Exception {
		
		/**
		  重启后发现还有未结束直播间，继续同步数据 | cacheKey[activityDataSyn|dfhuf520@126.com|1827550502393204]
		  重启后发现| cacheKeyArray ["activityDataSyn|dfhuf520@126.com|1827550502393204"]
		 */
		if(!synTaskEnable) {
			return ;
		}
		
		//这里可以整改为如果服务器重启了可以读取redis中的数据来重新开始同步  可以通过 redisTemplate 实现
		syncLoadSysConfig();
		//这里是防止服务器重启后无法继续同步
		try {
			for(String key : subNameDeptid.keySet()) {
				//activityDataSyn_zlx_hs@outlook.com_1827438866730227
				for(Object cacheKey : redisTemplate.keys(cacheKey + key + "_*")) {
					System.out.println("重启后发现还有未结束直播间，继续同步数据 | cacheKey["+cacheKey+"]");
					String cacheKeyStr = (String) cacheKey;
					String state = redisCache.getCacheObject(cacheKeyStr);
					if("start".equals(state)) { //继续同步
						String[] cacheKeyArray = cacheKeyStr.split("_");
						if(cacheKeyArray.length != 3) {
							System.out.println("重启后发现| cacheKeyArray " + JSONObject.toJSONString(cacheKeyArray));
							return ;
						}
						String activityId = cacheKeyArray[2];
						String subName = cacheKeyArray[1];
						System.out.println("重启后发现还有未结束直播间，继续同步数据 | subName["+subName+"], activityId["+activityId+"]");
						
						//判断下直播是否结束
						GetActivityAPIResponse response = liveVideoService.getActivityInfo(Long.valueOf(activityId));
						if(response.getResult().getStatus() != 4) {
							startSync(activityId, subName);
							return ;
						}else {
							redisTemplate.delete(cacheKeyStr);
						}
					}
					
					System.out.println(" =========== | state cacheKey " + state );
				}
			}
		}catch(Exception e) {
			e.printStackTrace();
		}
		
	}

	/**
	* @Title: startSync 
	* @Description: TODO(根据直播间ID进行数据同步 一旦开播就开始统计) 
	* @param     设定文件 
	* @return void    返回类型 
	* @throws
	 */
	public void startSync(String activityId, String subName) {
		String assembleCacheKey = cacheKey + subName +"_" + activityId;
		String stopKey = assembleCacheKey+"_stop";
		
		if(redisCache.hasKey(stopKey)) { //判断当前有停止动作，所以先删除放置后续被线程暂停
			redisCache.deleteObject(stopKey);
		}
		
		redisCache.setCacheObject(assembleCacheKey, "start");
		LOG.error("直播开始 | 直播数据同步Key " + assembleCacheKey);
		new Thread(new Runnable() {
			@Override
			public void run() {
				while(true) {
					try {
						syncLoadSysConfig();
						long zjbid = Long.valueOf(activityId);
						PageClicksFormAPI pageClicksFormAPI = liveVideoService.getPageWatchData(zjbid);
			    		GetRealTimeOnlineNumberAPIResponse response = liveVideoService.getRealTimeOnlineNumber(zjbid);
						DateTime now = DateTime.now();
						LbsZbrqsj lbsZbrqsj = new LbsZbrqsj();
						lbsZbrqsj.setActivityId(activityId);
						lbsZbrqsj.setSubname(subName);
						lbsZbrqsj.setDeptZbjId(subNameDeptid.get(subName));
						lbsZbrqsj.setPv(pageClicksFormAPI.getPV().intValue());
						lbsZbrqsj.setUv(pageClicksFormAPI.getUV().intValue());
						lbsZbrqsj.setPcu(pageClicksFormAPI.getPCU().intValue());
						lbsZbrqsj.setTotalTime(pageClicksFormAPI.getTotalTime().intValue());
						lbsZbrqsj.setAvgNumber(BigDecimal.valueOf(pageClicksFormAPI.getAvgNumber()));
						lbsZbrqsj.setAvgTime(BigDecimal.valueOf(pageClicksFormAPI.getAvgTime()));
						lbsZbrqsj.setZsrs(response.getResult().getRealPopularity().intValue());
						lbsZbrqsj.setXnrs(response.getResult().getFakePopularity().intValue());
						String cssj = now.toString("yyyy-MM-dd HH:mm");
						lbsZbrqsj.setCssj(cssj);
						
						if(isSyncDataExist(activityId, cssj)) {
							lbsZbrqsjService.insert(lbsZbrqsj);
						}
						
						Thread.sleep(60000);
						if(!redisCache.hasKey(assembleCacheKey)) { //跳出循环
							break;
						}
					}catch(Exception e) {
						e.printStackTrace();
						System.out.println("直播间数据同步异常，继续同步数据 | subName["+subName+"], activityId["+activityId+"]");
						startSync(activityId, subName);
						break;
					}
				}
			}
		}).start();
	}
	
	
	
	/**
	* @Title: startSync 
	* @Description: TODO(根据直播间ID停止数据同步 - 直播停止后延迟5分钟在关闭统计) 
	* @param     设定文件 
	* @return void    返回类型 
	* @throws
	 */
	public void stopSync(String activityId, String subName) {
		String assembleCacheKey = cacheKey + subName +"_" + activityId;
		String stopKey = assembleCacheKey+"_stop";
		LOG.error("直播停止 | 直播数据同步Key " + assembleCacheKey);
		redisCache.setCacheObject(stopKey ,"stop", 8, TimeUnit.MINUTES);
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					//等待3分钟后结束直播数据同步
					Thread.sleep(180000);
					if(redisCache.hasKey(stopKey)) {
						redisCache.deleteObject(assembleCacheKey);
						redisCache.deleteObject(stopKey);
					}
				} catch (Exception e) {
				}
			}
		}).start();
	}


	private void syncLoadSysConfig() throws Exception {
		SysConfig sysConfig = configService.selectConfigByKey2("sys_config");
		if (null != sysConfig && !StrUtil.isBlankIfStr(sysConfig.getRemark())) {
			JSONObject sysConfigJsonObject = JSONObject.parseObject(sysConfig.getRemark());
			if (sysConfigJsonObject.containsKey("activityConfig")) {
				JSONArray activityConfigList = sysConfigJsonObject.getJSONArray("activityConfig");
				for (int i = 0; i < activityConfigList.size(); i++) {
					JSONObject item = activityConfigList.getJSONObject(i);
					subNameDeptid.put(item.getString("subusername"), item.getLong("zbjid"));
				}
			}
		}
	}
	
	
	
	/**
	* @Title: isSyncData 
	* @Description: TODO(这里防止通一分钟多条数据出现。) 
	* @param @return    设定文件 
	* @return boolean    返回类型 
	* @throws
	 */
	private boolean isSyncDataExist(String activityId, String cssj) {
		 QueryWrapper<LbsZbrqsj> query = new QueryWrapper<>();
         query.eq("activity_id", activityId);
         query.eq("cssj", cssj);
         LbsZbrqsj lbsZbrqsj = lbsZbrqsjMapper.selectOne(query);
         if(null != lbsZbrqsj) {
        	 return false;
         }
		 return true;
	}
	
	
	
	
	
}
